import utils from '../utils'

const {moment, axios} = require('../../node-test');
import log from '../logger'
import {PostData, WaitUpState} from "../interfaces";
import waitDownState from "./3waitDown";
import settings from "../settings";
import plate from "../plate";
import state from "./state";
import weighter from "../weight";
import player from "../player";
import rtsp from "../rtsp";
import led from "../led";
import controller from "../controller";
import e = require("express");

const WAIT_WEN_COUNT = 60

class WeightStateImpl implements WaitUpState {
    name = "WeightState"
    lock = false;
    // 防止磅重变0，此方法还在循环，weightState => readyState => weightState，条件为真
    waitWeightActiveIdent: symbol;

    init() {
        this.waitWeightActiveIdent = Symbol("waitWeightActiveIdent");
        this.lock = false;
        if (settings.barrierGate !== 'inout') {
            plate.manualTrigger(true)
        }
    }

    leave() {
        // 清除持久化状态，过磅完成后
        state.clearState();
        this.waitWeightActiveIdent = undefined;
        this.lock = false;
        if (settings.barrierGate !== 'inout') {
            plate.manualTrigger(false)
        }
    }

    plate(vehicleNumber: string, inout: 'in' | 'out'): void {
        if (settings.barrierGate !== 'inout') {
            state.addPlate(vehicleNumber, inout)
        }
    }

    active(R: boolean[]): void {
        if (state.isSale && settings.saleBtnWeighing && state.isSecond && !state.closeSaleBtnWeighing) {
            if (R[3] === true) {
                log.info("销售出库过磅按钮按下");
                this.weighing();
            }
            if (R[2] === true) {
                log.info("销售出库后退按钮按下")
                // 记录车号，防止倒车再次识别
                state.backVehicle = {
                    carNum: state.getVehicleNumber(),
                    time: new Date().getTime()
                }
                log.info("执行抬杆动作")
                state.isBack = true;
                state.stateContext = waitDownState;
                controller.openUpInout(state.inout);
            }
        }
    }

    async weighing() {
        if (this.lock) {
            return;
        }
        this.lock = true;
        player.say(`车号${state.getVehicleNumber().split('').join(' ')}，正在过磅，请稍后。`);
        try {
            const weightWen = await this._waitWeightActive(this.waitWeightActiveIdent);
            // 上传服务器
            let date = new Date();
            let photo = await rtsp.saveImg(state.inout, state.getVehicleNumber(), weightWen, moment(date).format('YYYY年MM月DD日HH时mm分'));
            const postData = {
                uuid: date.getTime(),
                deviceName: settings.deviceName,
                inout: state.inout,
                vehicleNumber: state.getVehicleNumber(),
                weight: weightWen,
                photoList: photo.photoList,
                photo: photo.photo,
                weighAddress: settings.name,
                createTime: moment(date).format('YYYY-MM-DD HH:mm:ss'),
                platformId: settings.platformId,
                containerSnOne: state.container1 === '' ? null : state.container1,
                containerSnTwo: state.container2 === '' ? null : state.container2,
            };
            log.info('postData', postData)
            try {
                await this._post(postData);
                this.weightDone(postData);
            } catch (e) {
                player.say(e)
                await utils.sleep(1000 * 10);
            }
        } catch (e) {
            // 过磅异常后现场手动过磅，抬杆下磅后状态不更新，导致后续车辆上磅异常
            state.clearState();
            player.say(e.message, 5);
        }
        this.lock = false
    }

    async weight_data(weight: number, wen: boolean) {
        if (weight <= 0.5 && wen || weight <= 0) {
            state.stateContext = waitDownState;
        } else if (state.hasVehicleNumber() && !this.lock) {
            // 销售二次过磅、按钮过磅
            if (state.isSale && settings.saleBtnWeighing && state.isSecond && !state.closeSaleBtnWeighing) {
                if (!this.lock) {
                    player.say("请按绿色按钮完成过磅，红色按钮倒车下磅");
                }
                // 采购集装箱、人工确认过磅
            } else if (state.isPurchase && state.manualDoWeigh) {
                if (!this.lock) {
                    player.say("请等待人工确认过磅完成");
                }
            } else {
                await this.weighing();
            }
        }
    }

    async do_weigh(weight: number, deductionWeight: number) {
        await this.manualWeighing(weight, deductionWeight);
    }

    async manualWeighing(weight: number, deductionWeight: number) {
        if (this.lock) {
            return;
        }
        this.lock = true;
        player.say(`车号${state.getVehicleNumber().split('').join(' ')}，正在过磅。`);
        try {
            // 上传服务器
            let date = new Date();
            let photo = await rtsp.saveImg(state.inout, state.getVehicleNumber(), weight, moment(date).format('YYYY年MM月DD日HH时mm分'));
            const postData = {
                uuid: date.getTime(),
                deviceName: settings.deviceName,
                inout: state.inout,
                vehicleNumber: state.getVehicleNumber(),
                deductionWeight: deductionWeight,
                weight: weight,
                photoList: photo.photoList,
                photo: photo.photo,
                weighAddress: settings.name,
                createTime: moment(date).format('YYYY-MM-DD HH:mm:ss'),
                platformId: settings.platformId,
                containerSnOne: state.container1 === '' ? null : state.container1,
                containerSnTwo: state.container2 === '' ? null : state.container2,
            };
            log.info('postData', postData)
            try {
                await this._post(postData);
                this.weightDone(postData);
            } catch (e) {
                player.say(e)
                await utils.sleep(1000 * 10);
            }
        } catch (e) {
            player.say(e.message);
        }
        this.lock = false
    }


    _post(postData: PostData) {
        return new Promise<string>((resole, reject) => {
            axios.post(settings.url + `/api/order/internal/bangDan/weighRecord/create/${settings.platformId}?syncWeight=${settings.asyncWeight}`, postData)
                .then((res: any) => {
                    if (res.data.code !== '0000') {
                        reject(res.data.msg);
                    } else {
                        resole('ok');
                    }
                })
                .catch(() => {
                    reject("网络错误，请联系管理员");
                });
        })
    }

    async _waitWeightActive(waitWeightActiveIdent: symbol) {
        let count = WAIT_WEN_COUNT
        while (count > 0 && this.waitWeightActiveIdent === waitWeightActiveIdent) {
            count--
            if (count % 15 === 0) {
                if (state.isBack) {
                    player.say('后退按钮已按下，请倒车缓慢下磅')
                } else {
                    if (!controller.R1 && weighter.wen) {
                        if (state.inout === 'in') {
                            player.say('车尾过线，请向前方移动')
                        } else {
                            player.say('车头过线，请向后方移动')
                        }
                    } else if (!controller.R2 && weighter.wen) {
                        if (state.inout === 'in') {
                            player.say('车头过线，请向后方移动')
                        } else {
                            player.say('车尾过线，请向前方移动')
                        }
                    } else if (!weighter.wen && weighter.weight > 0.5) {
                        player.say('正在等待稳定，请不要随意移动')
                    }
                }
            }
            if (!state.isBack) {
                log.info(`正在过磅：WEN:${weighter.wen}, R1:${controller.R1}, R2:${controller.R2},ignore:${controller.ignore}, WEIGHT:${weighter.weight},count:${count}`)
            }
            for (let i = 0; i < 4; i++) {
                if (weighter.wen && controller.R1 && controller.R2 && weighter.weight > 0.5) {
                    state.wenWeight = weighter.weight
                    return weighter.weight
                }
                await utils.sleep(250)
            }
        }
        throw new Error('等待稳定超时，请人工处理')
    }

    driverRequest(type: string): void {
    }

    weightDone(postData: PostData) {
        let sayText;
        if (settings.isSayWeight) {
            sayText = `车号${state.getVehicleNumber().split('').join(' ')}，重量${postData.weight}吨，过磅成功。`;
        } else {
            sayText = `车号${state.getVehicleNumber().split('').join(' ')}，过磅成功。`;
        }
        if (state.warehouse && !state.isSecond) {
            sayText += `请前往${state.warehouse},${state.location}装卸货。`
        }
        player.say(sayText, 2);
        led.send(state.getVehicleNumber(), postData.weight)
        // 用来准备上传重量变化
        state.weighRecordId = postData.uuid;
        controller.openDownInout(state.inout)
        state.stateContext = waitDownState;
    }
}

const weightState = new WeightStateImpl();
export default weightState;
